package com.ruoyi.combat.service.externalServiceInvoker;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.ruoyi.combat.domain.CombatMethod;
import com.ruoyi.combat.mapper.CombatMethodMapper;
import com.ruoyi.combat.util.MethodUseUtils;
import com.ruoyi.common.exception.base.BaseException;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
import java.util.Map;

/**
 * @author baijie
 * @date 2025/2/19
 * @description 请求外部接口，获取定位信息
 */
@Service
public class PinpointService {

    private static final Logger log = LoggerFactory.getLogger(PinpointService.class);
    @Autowired
    private CombatMethodMapper combatMethodMapper;
    @Autowired
    private MethodUseUtils methodUseUtils;

    /**
     * 基于高精度地标的定位方法
     * @param targetIP
     * @param cityName
     * @param lon
     * @param lat
     * @return
     */
    public Map<String, Object> pinpoint(String targetIP, String cityName, String lon, String lat) {
        // 获取外部请求接口信息
        // 判断是不是拼音，如果不是，转为拼音，并且首字符大写
        cityName = convertToPinyin(cityName);
        CombatMethod combatMethod = combatMethodMapper.selectCombatMethodById(24L);
        if (combatMethod == null) {
            log.error("未查询到定位算法");
            throw new RuntimeException("未查询到定位算法");
        }
        String methodUrl = combatMethod.getMethodUrl();
        if (StrUtil.isBlank(methodUrl)) {
            log.error("未查询到定位算法的请求地址");
            throw new RuntimeException("未查询到定位算法的请求地址");
        }
        // 安全地构建URL参数
        try {
            String encodedTargetIP = URLEncoder.encode(targetIP, StandardCharsets.UTF_8.toString());
            String encodedCityName = URLEncoder.encode(cityName, StandardCharsets.UTF_8.toString());
            String encodedLon = URLEncoder.encode(lon, StandardCharsets.UTF_8.toString());
            String encodedLat = URLEncoder.encode(lat, StandardCharsets.UTF_8.toString());

            String postParam = "targetIP=" + encodedTargetIP + "&cityName=" + encodedCityName + "&lon=" + encodedLon + "&lat=" + encodedLat;
            Map<String, Object> map = methodUseUtils.methodUseLogs(24L, postParam);
            Integer code = (Integer) map.get("code");
            String message = (String) map.get("message");

            if (200 == code) {
                log.info("请求定位算法成功");
                Map<String, Object> dataMap = (Map<String, Object>) map.get("data");
                return dataMap;
            } else {
                log.error("请求定位算法失败: {}", message);
                throw new BaseException("请求定位算法失败: " + message);
            }
        } catch (Exception e) {
            log.error("参数编码失败", e);
            throw new BaseException("参数编码失败");
        }
    }

    /**
     * 基于时延的定位方法
     */
    public void pinpointDelay(Long taskId, String targetIP, String cityName, String lon, String lat) {
        // 获取外部请求接口信息
        // 判断是不是拼音，如果不是，转为拼音，并且首字符大写
        cityName = convertToPinyin(cityName);
        CombatMethod combatMethod = combatMethodMapper.selectCombatMethodById(25L);
        if (combatMethod == null) {
            log.error("未查询到定位算法");
            throw new RuntimeException("未查询到定位算法");
        }
        String methodUrl = combatMethod.getMethodUrl();
        if (StrUtil.isBlank(methodUrl)) {
            log.error("未查询到定位算法的请求地址");
            throw new RuntimeException("未查询到定位算法的请求地址");
        }
        // 安全地构建URL参数
        try {
            String encodedTargetIP = URLEncoder.encode(targetIP, StandardCharsets.UTF_8.toString());
            String encodedCityName = URLEncoder.encode(cityName, StandardCharsets.UTF_8.toString());
            String encodedLon = URLEncoder.encode(lon, StandardCharsets.UTF_8.toString());
            String encodedLat = URLEncoder.encode(lat, StandardCharsets.UTF_8.toString());

            String postParam = "targetIP=" + encodedTargetIP + "&cityName=" + encodedCityName + "&lon=" + encodedLon + "&lat=" + encodedLat + "&taskId=" + taskId;
            Map<String, Object> map = methodUseUtils.methodUseLogs(25L, postParam);
            Integer code = (Integer) map.get("code");
            String message = (String) map.get("message");
            if (200 == code) {
                log.info("请求定位算法成功");
            } else {
                log.error("请求定位算法失败: {}", message);
                throw new BaseException("请求定位算法失败: " + message);
            }
        } catch (Exception e) {
            log.error("参数编码失败", e);
            throw new BaseException("参数编码失败");
        }
    }

    /**
     * 汉字转拼音
     */
    public String convertToPinyin(String cityName) {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        // 设置拼音小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 设置不带声调
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        StringBuilder pinyin = new StringBuilder();
        for (char c : cityName.toCharArray()) {
            try {
                String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
                if (pinyinArray != null && pinyinArray.length > 0) {
                    pinyin.append(pinyinArray[0]);
                } else {
                    pinyin.append(c);
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                log.error("汉字转拼音失败", e);
                throw new BaseException("汉字转拼音失败");
            }
        }
        String result = pinyin.toString();
        // 首字母大写
        result = result.toString().substring(0, 1).toUpperCase() + result.substring(1);
        return result;
    }

}
